﻿
using Google.ProtocolBuffers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Linq;
using System.Diagnostics;
using System.Threading;

namespace SLClient
{
    public partial class CommunicatorClient
    {
        #region Current
        private static CommunicatorClient _current;

        public static CommunicatorClient Current
        {
            get
            {
                return _current ?? (_current = new CommunicatorClient());
            }
        }
        #endregion

        public string Id
        {
            get;
            set;
        }


        private CommunicatorClient()
        {
        }

        public void Reset()
        {
            if (this.TcpChannel != null)
            {
                this.TcpChannel.Received -= this.TcpChannelReceived;
                this.TcpChannel.Error -= this.TcpChannelError;
                this.TcpChannel.Close();
            }
            this.Id = null;
            _current = null;
        }

        private Queue<byte[]> _sendQueue = null;

        private void TcpChannelError(object sender, TcpChannelErrorEventArgs e)
        {
            Debug.WriteLine(e.Exception.Message);

            if (this.Id == null)
            {
                return;
            }

            if (_sendQueue != null)
            {
                return;
            }

            Deployment.Current.Dispatcher.BeginInvoke(async () =>
            {
                this.OnStateChanged(1);

                while (true)
                {
                    if (this.TcpChannel != null)
                    {
                        this.TcpChannel.Received -= this.TcpChannelReceived;
                        this.TcpChannel.Error -= this.TcpChannelError;
                        this.TcpChannel.Close();

                        if (_sendQueue == null)
                        {
                            _sendQueue = this.TcpChannel.SendQueue;
                        }

                        this.TcpChannel = null;
                    }


                    await Task.Factory.StartNew(() => Thread.Sleep(1000));

                    try
                    {
                        await this.ConnectAsync();

                        var sendQueue = _sendQueue;
                        _sendQueue = null;

                        //var reconnect = new Reconnect.Builder().SetUniqueMark(this.Id).Build();
                        //var response = await this.Call<Reconnect, CommonResponse>(reconnect);
                        //if (response.Status == CommandStatus.success)
                        //{
                        //    while (true)
                        //    {
                        //        if (sendQueue.Count == 0)
                        //        {
                        //            this.OnStateChanged(0);
                        //            return;
                        //        }

                        //        var data = sendQueue.Dequeue();

                        //        this.TcpChannel.Send(data);
                        //    }
                        //}
                        //else
                        //{
                        //    this.OnAccountLogoutReceived();

                        //    return;
                        //}
                    }
                    catch
                    {
                    }
                }
            });
        }

        #region StateChanged
        public event EventHandler<CommunicatorClientStateChanged> StateChanged;

        protected void OnStateChanged(int state)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                if (this.StateChanged != null)
                {
                    this.StateChanged(this, new CommunicatorClientStateChanged(state));
                }
            });
        }
        #endregion
    }

    public class CommunicatorClientStateChanged : EventArgs
    {
        public CommunicatorClientStateChanged(int state)
        {
            this.State = state;
        }

        public int State
        {
            get;
            private set;
        }
    }
}
